package com.xbongbong.pro.statistic.help;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.vo.ExportFormDataVO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisConstant;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.domain.entity.ChartEntity;
import com.xbongbong.pro.enums.errorcodes.ExportErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ImportErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.service.toolbox.statistic.help.SystemChartHelp;
import com.xbongbong.pro.statistic.enums.ChartGroupSizeEnum;
import com.xbongbong.pro.statistic.enums.ChartTypeEnum;
import com.xbongbong.pro.statistic.enums.StatisticsTypeEnum;
import com.xbongbong.pro.statistic.enums.SystemCodeEnum;
import com.xbongbong.pro.statistic.pojo.ExportStatusPojo;
import com.xbongbong.pro.statistic.result.pojo.ChartIdPojo;
import com.xbongbong.pro.statistic.result.pojo.PkInfoPojo;
import com.xbongbong.pro.statistic.result.pojo.TitlePojo;
import com.xbongbong.pro.statistic.result.pojo.TitleRightPojo;
import com.xbongbong.pro.statistic.result.pojo.dto.ChartPenetrateResultDTO;
import com.xbongbong.pro.statistic.result.pojo.vo.CallStatisticsVO;
import com.xbongbong.pro.statistic.result.pojo.vo.ChartResultDetailVO;
import com.xbongbong.pro.statistic.result.pojo.vo.ChartResultVO;
import com.xbongbong.pro.statistic.result.pojo.vo.PerformanceFinishVO;
import com.xbongbong.pro.statistic.result.pojo.vo.ResultDataTableVO;
import com.xbongbong.pro.statistic.result.pojo.vo.ResultTableVO;
import com.xbongbong.pro.statistic.service.HandleImportService;
import com.xbongbong.pro.statistic.through.pojo.TableDataInfoNewPojo;
import com.xbongbong.pro.statistic.through.pojo.TableDataInfoPojo;
import com.xbongbong.pro.statistic.through.pojo.vo.ResultThroughVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ErrorMessageConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.constant.export.ExportConstant;
import com.xbongbong.saas.constant.export.ImportConstant;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 导出功能相关
 * @author zhouwq
 * @date 2019/5/30 14:41
 */
@Component
public class ChartExportHelp {

    /**
     * 统计表 导出功能中记录row游标
     */
    private static int idx = 0;

    public static CellStyle numberStyle;

    private static void setIdx(int idx) {
        ChartExportHelp.idx = idx;
    }

    @Resource
    private SystemChartHelp systemChartHelp;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private HandleImportService handleImportService;
    public Logger logger = LoggerFactory.getLogger(getClass());


    /**
     * 导出workBook数据组装 查询表
     * @param resultTableVO 导出内容详情
     * @param sheet 工作表
     * @param style 样式
     * @author zhouwq
     * @date 2019/5/29 14:13
     */
    public void exportQueryTableAssemble(ResultTableVO resultTableVO, SXSSFSheet sheet, CellStyle style) throws XbbException{
        List<JSONObject> customTitle = resultTableVO.getCustomTitle();
        List<JSONObject> customData = resultTableVO.getCustomData();
        Map<String, Integer> titleMap = new HashMap<>(customTitle.size());
        Map<String, Map<String, Integer>> subTitleMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        try {
            //表头标题行创建
            initWorkBookTitle(customTitle, sheet, style, titleMap, subTitleMap);
            //初始主要数据开始的row游标
            int rowIdx = 2;
            //主要内容
            for (JSONObject data : customData) {
                //数据内子表单最大size
                int subMaxSize = 0;
                SXSSFRow row = sheet.createRow(rowIdx);
                for (JSONObject object : customTitle) {
                    String key = object.getString("key");
                    if (FieldTypeEnum.isSubFormType(object.getInteger("fieldType"))) {
                        JSONArray subFormData = data.getJSONArray(key);
                        if(subFormData != null){
                            Map<String, Integer> subDataTitleMap = subTitleMap.get(key);
                            for (int x = 0; x < subFormData.size(); x++) {
                                JSONObject subFormObject = subFormData.getJSONObject(x);
                                if(subFormObject != null && subFormObject.size() > 0) {
                                    SXSSFRow subRow;
                                    if (sheet.getRow(rowIdx + x) == null) {
                                        subRow = sheet.createRow(rowIdx + x);
                                    } else {
                                        subRow = sheet.getRow(rowIdx + x);
                                    }
                                    subDataTitleMap.forEach((subKey, cellNum) -> {
                                        SXSSFCell subCell = subRow.createCell(cellNum);
                                        subCell.setCellValue(subFormObject.getString(subKey));
                                        subCell.setCellStyle(style);
                                    });
//                                    rowIdx++;
                                }
                                if(subFormData.size() > subMaxSize){
                                    subMaxSize = subFormData.size();
                                }
                            }
//                            rowIdx--;
                        }
                    } else if (Objects.equals(FieldTypeEnum.LABEL.getType(),object.getInteger("fieldType"))){
                        JSONArray labels = data.getJSONArray(key);
                        StringBuilder labelName = new StringBuilder();
                        for (Object item : labels) {
                            JSONObject jsonObject = (JSONObject) item;
                            if (labelName.length() != 0){
                                labelName.append(StringConstant.COMMA);
                            }
                            labelName.append(jsonObject.getString("name"));
                        }
                        SXSSFCell cellData = row.createCell(titleMap.get(key));
                        cellData.setCellValue(labelName.toString());
                        cellData.setCellStyle(style);
                    }else {
                        String value = data.getString(key);
                        SXSSFCell cellData = row.createCell(titleMap.get(key));
                        cellData.setCellValue(value);
                        cellData.setCellStyle(style);
                    }
                }
                subMaxSize = subMaxSize == 0 ? 1 : subMaxSize;
                rowIdx = rowIdx + subMaxSize;
            }
        }catch (XbbException e){
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), e.getMessage());
        }
    }

    /**
     * 导出workBook数据组装
     * @param resultTableVO 导出内容详情
     * @param groupSize 分组层级
     * @param sheet 工作表
     * @param style 样式
     * @author zhouwq
     * @date 2019/5/29 14:13
     */
    public void exportStatisticsTableAssemble(ResultTableVO resultTableVO, Integer groupSize, SXSSFSheet sheet, CellStyle style){
        List<JSONObject> customTitle = resultTableVO.getCustomTitle();
        List<JSONObject> customData = resultTableVO.getCustomData();
        Map<String, Integer> titleMap = new HashMap<>(customTitle.size());
        //表头标题行创建
        initWorkBookTitle(customTitle, sheet, style, titleMap);
        JSONArray customTotal = resultTableVO.getCustomTotal();
        Integer chartType = resultTableVO.getChartType();
        setIdx(idx + 1);
        //主要内容
        for(int i = 0,size = customData.size(); i < size; i++ ){
            JSONObject data = customData.get(i);
            JSONObject totalObj = new JSONObject();
            // ck版渲染指标图时不返回customTotal
            if (!Objects.equals(chartType, ChartTypeEnum.TARGET_CHART.getCode())) {
                totalObj = customTotal.getJSONObject(i);
            }
            ChartGroupSizeEnum chartGroupSizeEnum = ChartGroupSizeEnum.getByCode(groupSize);
            if(chartGroupSizeEnum != null) {
                switch (chartGroupSizeEnum) {
                    case GROUP_FIRST:
                        statisticsRowsAssembleFirst(data, sheet, totalObj, style, titleMap);
                        break;
                    case GROUP_SECOND:
                        statisticsRowsAssembleSecond(data, customTitle, sheet, totalObj, style, titleMap);
                        break;
                    case GROUP_THIRD:
                        int firstRow = idx;
                        statisticsRowsAssembleThird(data, customTitle, sheet, totalObj, style, titleMap);
                        int lastRow = idx - 2;
                        if(lastRow > firstRow) {
                            CellRangeAddress region = new CellRangeAddress(firstRow, lastRow, 0, 0);
                            sheet.addMergedRegion(region);
                        }
                        break;
                    default:
                        break;
                }
            }
        }

        //导出成功后置为0
        setIdx(0);
    }

    /**
     * 系统图表导出workBook组装
     * @param resultTableVO 导出内容详情
     * @param sheet 工作表
     * @param style 样式
     * @author zhouwq
     * @date 2019/5/30 8:27
     */
    public void exportSystemChartAssemble(ResultTableVO resultTableVO, SXSSFSheet sheet, CellStyle style){
        List<String> titleList = systemChartHelp.getTitleValue(resultTableVO.getTitle());
        List<List<ResultDataTableVO>> dataList = resultTableVO.getData();
        int idx = 0;
        if(dataList != null && dataList.size() > 0) {
            //描述信息内容
            String headMemo = resultTableVO.getHeadMemo();
            int cellLength = dataList.get(0).size();
            if (headMemo != null) {
                SXSSFRow row = sheet.createRow(idx);
                SXSSFCell cell = row.createCell(0);
                cell.setCellValue(headMemo);
                cell.setCellStyle(style);
                CellRangeAddress region1 = new CellRangeAddress(0, 1, 0, cellLength - 1);
                sheet.addMergedRegion(region1);
                idx += 2;
            }
            //表头标题行创建
            SXSSFRow rowTitle = sheet.createRow(idx);
            idx++;
            initWorkBookSystemTitle(titleList, rowTitle, sheet, style);
            for (int i = 0, dataSize = dataList.size(); i < dataSize; i++) {
                List<ResultDataTableVO> tableVOList = dataList.get(i);
                SXSSFRow row = sheet.createRow(i + idx);
                for (int y = 0, size = tableVOList.size(); y < size; y++) {
                    ResultDataTableVO resultDataTableVO = tableVOList.get(y);
                    SXSSFCell cell = row.createCell(y);
                    cell.setCellValue(resultDataTableVO.getValue());
                    cell.setCellStyle(style);
                }
            }
        }
    }

    /**
     * 系统图表导出workBook组装（数据是businessData）
     *
     * @param resultTableVO 导出内容详情
     * @param sheet 工作表
     * @param style 样式
     * @author 徐俊杰
     * @date 2020/3/21 14:48
     * @since v1.0
     */
    public void exportSystemChartAssemble4BusinessData(ResultTableVO resultTableVO, SXSSFSheet sheet, CellStyle style){
        List<TitleRightPojo> title = resultTableVO.getTitle();
        List<String> titleList = systemChartHelp.getTitleValue(title);
        List<List<TableDataInfoNewPojo>> businessData = resultTableVO.getBusinessData();
        int idx = 0;
        if(businessData != null && businessData.size() > 0) {
            //表头标题行创建
            SXSSFRow rowTitle = sheet.createRow(idx);
            idx++;
            initWorkBookSystemTitle(titleList, rowTitle, sheet, style);
            for (int i = 0, dataSize = businessData.size(); i < dataSize; i++) {
                List<TableDataInfoNewPojo> tableVOList = businessData.get(i);
                SXSSFRow row = sheet.createRow(i + idx);
                for (int y = 0, size = tableVOList.size(); y < size; y++) {
                    TableDataInfoNewPojo resultDataTableVO = tableVOList.get(y);
                    SXSSFCell cell = row.createCell(y);
                    cell.setCellValue(resultDataTableVO.getValue());
                    cell.setCellStyle(style);
                }
            }
        }
    }

    /**
     * 机会阶段变更分析导出workBook组装
     * @param resultTableVO 导出内容详情
     * @param sheet 工作表
     * @param style 样式
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public void exportSystemChartAssemble4OpportunityStage(ResultTableVO resultTableVO, SXSSFSheet sheet, CellStyle style){
        List<List<ResultDataTableVO>> dataList = resultTableVO.getData();
        int idx = 0;
        if(dataList != null && dataList.size() > 0) {
            //描述信息内容
            String headMemo = resultTableVO.getHeadMemo();
            int cellLength = dataList.get(0).size();
            if (headMemo != null) {
                SXSSFRow row = sheet.createRow(idx);
                SXSSFCell cell = row.createCell(0);
                cell.setCellValue(headMemo);
                cell.setCellStyle(style);
                CellRangeAddress region1 = new CellRangeAddress(0, 1, 0, cellLength - 1);
                sheet.addMergedRegion(region1);
                idx += 2;
            }
            //表头标题行创建
            //0行
            SXSSFRow rowTitle = sheet.createRow(idx);
            idx++;
            //1行
            SXSSFRow rowTitle2 = sheet.createRow(idx);
            idx++;
            initWorkBookSystemTitle4Merge(resultTableVO.getTitle(), rowTitle, rowTitle2, sheet, style);
            for (int i = 0, dataSize = dataList.size(); i < dataSize; i++) {
                List<ResultDataTableVO> tableVOList = dataList.get(i);
                SXSSFRow row = sheet.createRow(i + idx);
                for (int y = 0, size = tableVOList.size(); y < size; y++) {
                    ResultDataTableVO resultDataTableVO = tableVOList.get(y);
                    SXSSFCell cell = row.createCell(y);
                    cell.setCellValue(resultDataTableVO.getValue());
                    cell.setCellStyle(style);
                }
            }
        }
    }

    /**
     * 穿透报表导出
     * @param resultThroughVO 导出内容详情
     * @param sheet 工作表
     * @param style 样式
     * @author zhouwq
     * @date 2019/5/30 16:28
     */
    public void exportThroughChartTableAssemble(ResultThroughVO resultThroughVO, SXSSFSheet sheet, CellStyle style){
        JSONArray data = resultThroughVO.getData();
        List<TitlePojo> pojoList = resultThroughVO.getTitle();
        //表头标题行创建
        Map<String, Integer> titleMap = new HashMap<>(pojoList.size());
        SXSSFRow rowTitle = sheet.createRow(0);
        for(int i = 0,size = pojoList.size(); i < size; i++){
            SXSSFCell cell = rowTitle.createCell(i);
            cell.setCellValue(pojoList.get(i).getValue());
            cell.setCellStyle(style);
            titleMap.put(pojoList.get(i).getKey(),i);
            //设置宽度
            sheet.setColumnWidth(i, 50 * 160);
        }

        for(int i = 0; i < data.size(); i++){
            SXSSFRow rowData = sheet.createRow(i+1);
            JSONObject dataObj = data.getJSONObject(i);
            titleMap.forEach((key, value) ->{
                SXSSFCell cell = rowData.createCell(value);
                cell.setCellStyle(style);
                TableDataInfoPojo tableDataInfoPojo = (TableDataInfoPojo)dataObj.get(key);
                cell.setCellValue(tableDataInfoPojo.getValue());
            });
        }
    }

    /**
     * 呼叫统计导出
     *
     * @param callStatisticsVO 导出内容详情
     * @param outOrIn 呼入/呼出
     * @param sheet 工作表
     * @param style 样式
     * @author youli.chen
     * @date 2019/6/20 21:34
     * @since v1.0
     */
    public void exportCallStatistics(CallStatisticsVO callStatisticsVO, boolean outOrIn, SXSSFSheet sheet, CellStyle style) {
        //creat
        JSONArray dataPojos = callStatisticsVO.getData();
        List<TitlePojo> titlePojos = callStatisticsVO.getTitle();
        //0行
        SXSSFRow zeroRow = sheet.createRow(0);

        //0行0列
        SXSSFCell zeroRowZeroCell = zeroRow.createCell(0);
        zeroRowZeroCell.setCellStyle(style);
        zeroRowZeroCell.setCellValue(titlePojos.get(0).getValue());
        //0行1列
        SXSSFCell zeroRowOneCell = zeroRow.createCell(1);
        zeroRowOneCell.setCellStyle(style);
        zeroRowOneCell.setCellValue(titlePojos.get(1).getValue());
        //0行2列
        SXSSFCell zeroRowTwoCell = zeroRow.createCell(2);
        zeroRowTwoCell.setCellStyle(style);
        zeroRowTwoCell.setCellValue(titlePojos.get(2).getValue());
        //0行3列
        SXSSFCell zeroRowThreeCell = zeroRow.createCell(3);
        zeroRowThreeCell.setCellStyle(style);
        zeroRowThreeCell.setCellValue(titlePojos.get(3).getValue());
        //0行4列
        SXSSFCell zeroRowFourCell = zeroRow.createCell(4);
        zeroRowFourCell.setCellStyle(style);
        zeroRowFourCell.setCellValue(titlePojos.get(4).getValue());
        //0行5列
        SXSSFCell zeroRowFiveCell = zeroRow.createCell(5);
        zeroRowFiveCell.setCellStyle(style);
        zeroRowFiveCell.setCellValue(titlePojos.get(5).getValue());
        //0行6列
        SXSSFCell zeroRowSixCell = zeroRow.createCell(6);
        zeroRowSixCell.setCellStyle(style);
        zeroRowSixCell.setCellValue(titlePojos.get(6).getValue());
        //0行7列
        SXSSFCell zeroRowSevenCell = zeroRow.createCell(7);
        zeroRowSevenCell.setCellStyle(style);
        zeroRowSevenCell.setCellValue(titlePojos.get(7).getValue());

        //处理标题
        callTitle(titlePojos, 8, zeroRow, sheet, style);

        //处理数据
        for (int i = 0; i < dataPojos.size(); i++) {
            SXSSFRow row = sheet.createRow(i + 1);
            JSONObject data = dataPojos.getJSONObject(i);
            //处理序号值
            SXSSFCell zeroCell = row.createCell(0);
            zeroCell.setCellStyle(style);
            zeroCell.setCellValue(data.getString("serialNum"));
            //处理名字值
            SXSSFCell oneCell = row.createCell(1);
            oneCell.setCellStyle(style);
            oneCell.setCellValue(data.getString("name"));
            //处理部门值
            SXSSFCell twoCell = row.createCell(2);
            twoCell.setCellStyle(style);
            twoCell.setCellValue(data.getString("depName"));
            // 呼叫次数
            String callNum = outOrIn ? data.getString("callOutNum") : data.getString("callInNum");
            SXSSFCell threeCell = row.createCell(3);
            threeCell.setCellStyle(style);
            threeCell.setCellValue(callNum);
            // 呼叫成功数
            String successNum = outOrIn ? data.getString("callOutSuccessNum") : data.getString("callInSuccessNum");
            SXSSFCell fourCell = row.createCell(4);
            fourCell.setCellStyle(style);
            fourCell.setCellValue(successNum);
            // 呼叫成功率
            String successRate = outOrIn ? data.getString("callOutSuccessRate") : data.getString("callInSuccessRate");
            SXSSFCell fiveCell = row.createCell(5);
            fiveCell.setCellStyle(style);
            fiveCell.setCellValue(successRate);
            // 呼叫时长
            String callTime = outOrIn ? data.getString("callOutTime") : data.getString("callInTime");
            SXSSFCell sixCell = row.createCell(6);
            sixCell.setCellStyle(style);
            sixCell.setCellValue(callTime);
            // 平均呼叫时长
            String avgTime = outOrIn ? data.getString("callOutAverageTime") : data.getString("callInAverageTime");
            SXSSFCell sevenCell = row.createCell(7);
            sevenCell.setCellStyle(style);
            sevenCell.setCellValue(avgTime);

            // 平均数
            if(data.getString("average") != null) {
                CellRangeAddress region1 = new CellRangeAddress(i + 1, i + 1, 0, 2);
                sheet.addMergedRegion(region1);
                zeroCell.setCellValue(data.getString("average"));
            }
        }
    }

    /**
     * 目标完成情况导出（员工）
     *
     * @param performanceFinishVO 导出内容详情
     * @param sheet 工作表
     * @param style 样式
     * @author 徐俊杰
     * @date 2019/6/20 21:34
     * @since v1.0
     */
    public void exportPerformanceFinishUser(PerformanceFinishVO performanceFinishVO, SXSSFSheet sheet, CellStyle style) throws XbbException {
        //creat
        JSONArray dataPojos = performanceFinishVO.getData();
        List<TitlePojo> titlePojos = performanceFinishVO.getTitle();
        if (Objects.isNull(titlePojos)) {
            throw new XbbException(ImportErrorCodeEnum.API_ERROR_235005);
        }
        //值的标题-列map
        Map<String, Integer> valueTitleColMap = new HashMap<>((titlePojos.size() - 2) * 3);
        //0行
        SXSSFRow zeroRow = sheet.createRow(0);
        //0行0列
        SXSSFCell zeroRowZeroCell = zeroRow.createCell(0);
        zeroRowZeroCell.setCellStyle(style);
        zeroRowZeroCell.setCellValue(titlePojos.get(0).getValue());
        //0行1列
        SXSSFCell zeroRowOneCell = zeroRow.createCell(1);
        zeroRowOneCell.setCellStyle(style);
        zeroRowOneCell.setCellValue(titlePojos.get(1).getValue());
        //1行
        SXSSFRow oneRow = sheet.createRow(1);
        //处理目标完成情况的标题
        performanceFinishTitle(titlePojos, 2, zeroRow, oneRow, valueTitleColMap, style);
        //处理数据
        for (int i = 0; i < dataPojos.size(); i++) {
            SXSSFRow row = sheet.createRow(i + 2);
            JSONObject data = dataPojos.getJSONObject(i);
            //处理名字值
            SXSSFCell zeroCell = row.createCell(0);
            zeroCell.setCellStyle(style);
            zeroCell.setCellValue(data.getString("name"));
            //处理部门值
            SXSSFCell oneCell = row.createCell(1);
            oneCell.setCellStyle(style);
            oneCell.setCellValue(data.getString("depName"));
            //所有列数
            int colNum = (titlePojos.size() - 2) * 3 + 2;
            for (int j = 2; j < colNum; j++) {
                SXSSFCell cell = row.createCell(j);
                cell.setCellStyle(style);
                for (Map.Entry<String, Integer> entry : valueTitleColMap.entrySet()) {
                    Integer col = entry.getValue();
                    if (col == j) {
                        String value = data.getString(entry.getKey());
                        if (StringUtil.isEmpty(value)) {
                            continue;
                        }
                        if (Objects.equals(value, "-1.0") && (j % 3 == 2)) {
                            cell.setCellValue(I18nMessageUtil.getMessage(CommonConstant.NOT_SET));
                        } else if (Objects.equals(value, "-1.0") && (j % 3 == 1)) {
                            cell.setCellValue("--");
                        } else if (j % 3 == 1) {
                            StringBuilder percentValue = new StringBuilder(value);
                            percentValue.append("%");
                            cell.setCellValue(String.valueOf(percentValue));
                        } else {
                            cell.setCellValue(data.getString(entry.getKey()));
                        }
                    }
                }
            }
        }
        //merge
        CellRangeAddress nameTitleRegion = new CellRangeAddress(0, 1, 0, 0);
        CellRangeAddress depTitleRegion = new CellRangeAddress(0, 1, 1, 1);
        sheet.addMergedRegion(nameTitleRegion);
        sheet.addMergedRegion(depTitleRegion);
        //完成情况的标题合并
        int titleNum = 3;
        for (int i = 2; i < titlePojos.size(); i = i + titleNum) {
            CellRangeAddress performanceTitleRegion = new CellRangeAddress(0, 0, i, i + 2);
            sheet.addMergedRegion(performanceTitleRegion);
        }
    }

    /**
     * 目标完成情况导出（部门）
     *
     * @param performanceFinishVO 导出内容详情
     * @param sheet 工作表
     * @param style 样式
     * @author 徐俊杰
     * @date 2019/6/21 16:34
     * @since v1.0
     */
    public void exportPerformanceFinishDep(PerformanceFinishVO performanceFinishVO, SXSSFSheet sheet, CellStyle style) {
        //creat
        JSONArray dataPojos = performanceFinishVO.getData();
        List<TitlePojo> titlePojos = performanceFinishVO.getTitle();
        //值的标题-列map
        Map<String, Integer> valueTitleColMap = new HashMap<>((titlePojos.size() - 1) * 3);
        //0行
        SXSSFRow zeroRow = sheet.createRow(0);
        //0行0列
        SXSSFCell zeroRowZeroCell = zeroRow.createCell(0);
        zeroRowZeroCell.setCellStyle(style);
        zeroRowZeroCell.setCellValue(titlePojos.get(0).getValue());
        //1行
        SXSSFRow oneRow = sheet.createRow(1);
        //处理目标完成情况的标题
        performanceFinishTitle(titlePojos, 1, zeroRow, oneRow, valueTitleColMap, style);
        //处理数据
        for (int i = 0; i < dataPojos.size(); i++) {
            SXSSFRow row = sheet.createRow(i + 2);
            JSONObject data = dataPojos.getJSONObject(i);
            //处理部门值
            SXSSFCell oneCell = row.createCell(0);
            oneCell.setCellStyle(style);
            oneCell.setCellValue(data.getString("depName"));
            //所有列数
            int colNum = (titlePojos.size() - 1) * 3 + 1;
            for (int j = 1; j < colNum; j++) {
                SXSSFCell cell = row.createCell(j);
                cell.setCellStyle(style);
                for (Map.Entry<String, Integer> entry : valueTitleColMap.entrySet()) {
                    Integer col = entry.getValue();
                    if (col == j) {
                        String value = data.getString(entry.getKey());
                        if (StringUtil.isEmpty(value)) {
                            continue;
                        }
                        if (Objects.equals(value, "-1.0") && (j % 3 == 1)) {
                            cell.setCellValue(I18nMessageUtil.getMessage(CommonConstant.NOT_SET));
                        } else if (Objects.equals(value, "-1.0") && (j % 3 == 0)) {
                            cell.setCellValue("--");
                        } else if (j % 3 == 0) {
                            StringBuilder percentValue = new StringBuilder(value);
                            percentValue.append("%");
                            cell.setCellValue(String.valueOf(percentValue));
                        } else {
                            cell.setCellValue(data.getString(entry.getKey()));
                        }
                    }
                }
            }
        }
        //merge
        CellRangeAddress depTitleRegion = new CellRangeAddress(0, 1, 0, 0);
        sheet.addMergedRegion(depTitleRegion);
        //完成情况的标题合并
        int titleNum = 3;
        for (int i = 1; i < titlePojos.size(); i = i + titleNum) {
            CellRangeAddress performanceTitleRegion = new CellRangeAddress(0, 0, i, i + 2);
            sheet.addMergedRegion(performanceTitleRegion);
        }
    }

    /**
     * Pk榜导出
     * @param titleList 标题内容
     * @param data 导出内容详情
     * @param sheet 工作表
     * @param style 样式
     * @author zhouwq
     * @date 2019/6/19 10:16
     */
    public void exportPkChartDataAssemble(List<String> titleList, List<PkInfoPojo> data, SXSSFSheet sheet, CellStyle style){
        //表头标题行创建
        SXSSFRow rowTitle = sheet.createRow(0);
        initWorkBookSystemTitle(titleList, rowTitle, sheet, style);

        for(int i = 0; i < data.size(); i++){
            SXSSFRow rowData = sheet.createRow(i+1);
            for(int x = 0; x < titleList.size(); x++){
                SXSSFCell cell = rowData.createCell(x);
                cell.setCellStyle(style);
                //Pk数据导出title固定size为4 且标题顺序固定
                switch (x){
                    case 0:
                        cell.setCellValue(data.get(i).getName());
                        break;
                    case 1:
                        cell.setCellValue(data.get(i).getDepName());
                        break;
                    case 2:
                        cell.setCellValue(data.get(i).getValue());
                        break;
                    case 3:
                        cell.setCellValue(data.get(i).getRank());
                        break;
                    default:
                        break;
                }
            }
        }
    }

    /**
     * 统计表三层分组时数据组装
     * @param data row 详细数据
     * @param customTitle 标题
     * @param sheet 工作表
     * @param totalObj 统计计数详情
     * @param style cell特征
     * @param titleMap 表头与cell下标对应关系map
     * @author zhouwq
     * @date 2019/5/29 19:39
     */
    private static void statisticsRowsAssembleThird(JSONObject data, List<JSONObject> customTitle, SXSSFSheet sheet, JSONObject totalObj, CellStyle style, Map<String, Integer> titleMap){
        for (JSONObject object : customTitle) {
            String key = object.getString("key");
            JSONObject valueObject = data.getJSONObject(key);
            if(valueObject == null){
                continue;
            }
            JSONArray subArray = valueObject.getJSONArray("sub");
            if(subArray != null){
                if(subArray.size() == 0){
                    SXSSFRow row = sheet.createRow(idx);
                    SXSSFCell cellData = row.createCell(titleMap.get(key));
                    cellData.setCellValue(valueObject.getString("value"));
                    cellData.setCellStyle(style);
                    idx++;
                }else {
                    for (int x = 0; x < subArray.size(); x++) {
                        JSONObject subObject = subArray.getJSONObject(x);
                        String keyTwo = subObject.keySet().iterator().next();
                        JSONObject subObjectTwo = subObject.getJSONObject(keyTwo);
                        String subValue = subObjectTwo.getString("value");
                        String subKey = subObjectTwo.getString("key");
                        JSONArray subArrayTwo = subObjectTwo.getJSONArray("sub");
                        int firsRow = idx;
                        if (subArrayTwo.size() == 0) {
                            SXSSFRow row = sheet.createRow(idx);
                            SXSSFCell cellData = row.createCell(titleMap.get(key));
                            cellData.setCellValue(valueObject.getString("value"));
                            cellData.setCellStyle(style);
                            SXSSFCell cellSubData = row.createCell(titleMap.get(subKey));
                            cellSubData.setCellValue(subValue);
                            cellSubData.setCellStyle(style);
                            idx++;
                        } else {
                            for (int y = 0; y < subArrayTwo.size(); y++) {
                                JSONObject objectTwo = subArrayTwo.getJSONObject(y);
                                SXSSFRow row = sheet.createRow(idx);
                                for (String keyObj : objectTwo.keySet()) {
                                    JSONObject valueTwo = objectTwo.getJSONObject(keyObj);

                                    SXSSFCell cellData = row.createCell(titleMap.get(key));
                                    cellData.setCellValue(valueObject.getString("value"));
                                    cellData.setCellStyle(style);
                                    SXSSFCell cellSubData = row.createCell(titleMap.get(subKey));
                                    cellSubData.setCellValue(subValue);
                                    cellSubData.setCellStyle(style);
                                    SXSSFCell cellSubTwo = row.createCell(titleMap.get(keyObj));
                                    cellSubTwo.setCellValue(valueTwo.getString("value"));
                                    cellSubTwo.setCellStyle(style);
                                }
                                idx++;
                            }
                        }
                        int lastRow = idx - 1;
                        if(lastRow > firsRow) {
                            CellRangeAddress region = new CellRangeAddress(firsRow, lastRow, 1, 1);
                            sheet.addMergedRegion(region);
                        }
                    }
                }
            }
        }
        countRowsAdd(sheet, style, totalObj, titleMap);
    }

    /**
     * 统计表双层分组时数据组装
     * @param data row 详细数据
     * @param customTitle 标题
     * @param sheet 工作表
     * @param totalObj 统计计数详情
     * @param style cell特征
     * @param titleMap 表头与cell下标对应关系map
     * @author zhouwq
     * @date 2019/5/29 19:39
     */
    private static void statisticsRowsAssembleSecond(JSONObject data, List<JSONObject> customTitle, SXSSFSheet sheet, JSONObject totalObj, CellStyle style, Map<String, Integer> titleMap){
        for (JSONObject object : customTitle) {
            String key = object.getString("key");
            JSONObject valueObject = data.getJSONObject(key);
            if(valueObject == null){
                continue;
            }
            JSONArray subArray = valueObject.getJSONArray("sub");
            if(subArray != null){
                //合并单元格起始row
                int fistRow = idx;
                if(subArray.size() == 0){
                    SXSSFRow row = sheet.createRow(idx);
                    SXSSFCell cellData = row.createCell(titleMap.get(key));
                    cellData.setCellValue(valueObject.getString("value"));
                    cellData.setCellStyle(style);
                    idx++;
                }else {
                    for (int x = 0; x < subArray.size(); x++) {
                        JSONObject subObject = subArray.getJSONObject(x);
                        SXSSFRow row = sheet.createRow(idx);
                        for (String keyObj : subObject.keySet()) {
                            JSONObject valueTwo = subObject.getJSONObject(keyObj);
                            SXSSFCell cellData = row.createCell(titleMap.get(key));
                            cellData.setCellValue(valueObject.getString("value"));
                            cellData.setCellStyle(style);
                            SXSSFCell cellSubTwo = row.createCell(titleMap.get(keyObj));
                            cellSubTwo.setCellValue(valueTwo.getString("value"));
                            cellSubTwo.setCellStyle(style);
                        }
                        idx++;
                    }
                    //合并单元格结束row
                    int lastRow = idx - 1;
                    if(lastRow > fistRow) {
                        CellRangeAddress region = new CellRangeAddress(fistRow, lastRow, 0, 0);
                        sheet.addMergedRegion(region);
                    }
                }
            }
        }
        countRowsAdd(sheet, style, totalObj, titleMap);
    }

    /**
     * 统计表单层分组时数据组装
     * @param data row 详细数据
     * @param sheet 工作表
     * @param totalObj 统计计数详情
     * @param style cell特征
     * @param titleMap 表头与cell下标对应关系map
     * @author zhouwq
     * @date 2019/5/29 19:39
     */
    private static void statisticsRowsAssembleFirst(JSONObject data, SXSSFSheet sheet, JSONObject totalObj, CellStyle style, Map<String, Integer> titleMap){
        SXSSFRow rowFirst = sheet.createRow(idx);
        for(String keyObj : data.keySet()){
            JSONObject valueTwo = data.getJSONObject(keyObj);
            SXSSFCell cellSubTwo = rowFirst.createCell(titleMap.get(keyObj));
            cellSubTwo.setCellValue(valueTwo.getString("value"));
            cellSubTwo.setCellStyle(style);
        }
        idx++;
//        countRowsAdd(sheet, style, totalObj, titleMap);
    }

    /**
     * 初始化标题行
     * @param customTitle 标题
     * @param sheet 工作表
     * @param style 样式
     * @param titleMap 表头与cell下标对应关系map
     * @author zhouwq
     * @date 2019/5/30 16:31
     */
    private static void initWorkBookTitle(List<JSONObject> customTitle, SXSSFSheet sheet, CellStyle style, Map<String, Integer> titleMap){
        //表头标题行创建
        SXSSFRow rowTitle = sheet.createRow(0);
//        SXSSFRow rowTitleSecond = sheet.createRow(1);
        for(int i = 0,size = customTitle.size(); i < size; i++ ){
            SXSSFCell cell = rowTitle.createCell(i);
            cell.setCellValue(customTitle.get(i).getString("name"));
            cell.setCellStyle(style);
            titleMap.put(customTitle.get(i).getString("key"),i);
            //设置宽度
            sheet.setColumnWidth(i, 50 * 160);
        }
    }

    /**
     * 初始化标题行
     * @param customTitle 标题
     * @param sheet 工作表
     * @param style 样式
     * @param titleMap 表头与cell下标对应关系map
     * @param subTitleMap 表头与cell下标对应关系map-子表单用
     * @author zhouwq
     * @date 2019/5/30 16:31
     */
    private static void initWorkBookTitle(List<JSONObject> customTitle, SXSSFSheet sheet, CellStyle style, Map<String, Integer> titleMap, Map<String, Map<String, Integer>> subTitleMap) throws XbbException {
        //表头标题行创建
        SXSSFRow rowTitle = sheet.createRow(0);
        SXSSFRow rowSecondTitle = sheet.createRow(1);
        int cellIdx = 0;
        for (JSONObject jsonObject : customTitle) {
            SXSSFCell cell = rowTitle.createCell(cellIdx);
            Integer fieldType = jsonObject.getInteger("fieldType");
            String key = jsonObject.getString("key");
            String name = jsonObject.getString("name");
            cell.setCellValue(name);
            cell.setCellStyle(style);
            if (FieldTypeEnum.isSubFormType(fieldType)) {
                JSONArray items = jsonObject.getJSONArray("items");
                int firstCol = cellIdx;
                Map<String, Integer> subMap = new HashMap<>(items.size());
                for (int x = 0; x < items.size(); x++) {
                    JSONObject objectItem = items.getJSONObject(x);
                    SXSSFCell cellSub = rowSecondTitle.createCell(cellIdx);
                    cellSub.setCellValue(objectItem.getString("name"));
                    subMap.put(objectItem.getString("key"), cellIdx);
                    sheet.setColumnWidth(cellIdx, 50 * 160);
                    cellIdx++;
                }
                subTitleMap.put(key, subMap);
                cellIdx--;
                CellRangeAddress regionSubForm = new CellRangeAddress(0, 0, firstCol, cellIdx);
                if(cellIdx > firstCol){
                    sheet.addMergedRegion(regionSubForm);
                }
            }else{
                CellRangeAddress region = new CellRangeAddress(0, 1, cellIdx, cellIdx);
                sheet.addMergedRegion(region);
            }
            titleMap.put(key, cellIdx);
            //设置宽度
            sheet.setColumnWidth(cellIdx, 50 * 160);
            cellIdx++;
        }
    }

    /**
     * 初始化系统标题行
     * @param titleList 标题
     * @param rowTitle 标题row
     * @param sheet 工作表
     * @param style 样式
     * @author zhouwq
     * @date 2019/6/19 10:14
     */
    private static void initWorkBookSystemTitle(List<String> titleList, SXSSFRow rowTitle, SXSSFSheet sheet, CellStyle style){
        for (int i = 0, size = titleList.size(); i < size; i++) {
            SXSSFCell cell = rowTitle.createCell(i);
            cell.setCellValue(titleList.get(i));
            cell.setCellStyle(style);
            //设置宽度
            sheet.setColumnWidth(i, 50 * 160);
        }
    }
    /**
     * 机会阶段变更分析统计标题初始化
     * @param titleList 标题数据
     * @param rowTitle 标题第一行（索引0）
     * @param rowTitle2 标题第二行（索引1）
     * @param sheet 工作表
     * @param style 样式
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private static void initWorkBookSystemTitle4Merge(List<TitleRightPojo> titleList, SXSSFRow rowTitle, SXSSFRow rowTitle2, SXSSFSheet sheet, CellStyle style){
        //最小粒度，逐列增加（合并几列算几个）
        int index = 0;
        //每次渲染的横向列索引（合并的一次加上被合并列数）的index
        int colIndex = 0;
        int lastColIndex = 0;
        for (int i = 0, size = titleList.size(); i < size; i++) {
            TitleRightPojo titleRightPojo = titleList.get(i);
            Integer col = titleRightPojo.getCol();
            Integer row = titleRightPojo.getRow();
            if (Objects.nonNull(col) && col > BasicConstant.ONE) {
                //需要多合并col行，但CellRangeAddress索引从0开始，因此减一
                lastColIndex += col-1;
                CellRangeAddress cellAddresses = new CellRangeAddress(0, 0, colIndex, lastColIndex);
                sheet.addMergedRegion(cellAddresses);
            }
            if (Objects.nonNull(row) && row > BasicConstant.ONE) {
                //需要多合并row行，但CellRangeAddress索引从0开始，因此减一
                row--;
                CellRangeAddress cellAddresses = new CellRangeAddress(0, row, colIndex, lastColIndex);
                sheet.addMergedRegion(cellAddresses);
            }
            SXSSFCell cell = rowTitle.createCell(colIndex);
            cell.setCellValue(titleRightPojo.getTitleValue());
            cell.setCellStyle(style);

            //处理子标题
            List<TitleRightPojo> children = titleRightPojo.getChildren();
            if (CollectionUtils.isNotEmpty(children)) {
                for (int j = 0; j < children.size(); j++) {
                    TitleRightPojo child = children.get(j);
                    int oneRowCol = colIndex + j;
                    SXSSFCell oneRowCell = rowTitle2.createCell(oneRowCol);
                    oneRowCell.setCellStyle(style);
                    oneRowCell.setCellValue(child.getTitleValue());
                    //设置宽度
                    sheet.setColumnWidth(index, 50 * 80);
                    index++;
                }
            } else {
                //设置宽度
                sheet.setColumnWidth(i, 50 * 80);
                index++;
            }
            if (col > 1) {
                colIndex += col;
            } else {
                colIndex++;
            }
            lastColIndex = colIndex;
        }
    }
    /**
     *
     * @param sheet 工作表
     * @param style 样式
     * @param totalObj 小计total详情
     * @param titleMap 表头与cell下标对应关系map
     * @author zhouwq
     * @date 2019/5/30 16:31
     */
    private static void countRowsAdd(SXSSFSheet sheet, CellStyle style, JSONObject totalObj, Map<String, Integer> titleMap){
        SXSSFRow row = sheet.createRow(idx);
        SXSSFCell cellCount = row.createCell(0);
        cellCount.setCellValue(I18nMessageUtil.getMessage(CommonConstant.SUBTOTAL));
        cellCount.setCellStyle(style);
        for(String key : totalObj.keySet()){
            SXSSFCell cellData = row.createCell(titleMap.get(key));
            String value = totalObj.getString(key);
            cellData.setCellValue(value);
            cellData.setCellStyle(style);
        }
        idx++;
    }

    /**
     * 标题处理
     *
     * @param titlePojos 标题
     * @param startTitle 开始的title是第几个
     * @param zeroRow 零行
     * @param style 样式
     * @author 徐俊杰
     * @date 2019/6/21 16:33
     * @since v1.0
     */
    private void callTitle(List<TitlePojo> titlePojos, int startTitle, SXSSFRow zeroRow, SXSSFSheet sheet, CellStyle style) {
        for(int i = 0,size = titlePojos.size(); i < size; i++ ){
            // 设置宽度
            sheet.setColumnWidth(i, 50 * 160);
        }
        //处理标题
        for (int i = startTitle; i < titlePojos.size(); i++) {
            TitlePojo titlePojo = titlePojos.get(i);
            int col = (i - startTitle) * 3 + startTitle;
            SXSSFCell zeroRowCell = zeroRow.createCell(col);
            zeroRowCell.setCellStyle(style);
            zeroRowCell.setCellValue(titlePojo.getValue());


        }
    }

    /**
     * 标题处理
     *
     * @param titlePojos 标题
     * @param startTitle 开始的title是第几个
     * @param zeroRow 零行
     * @param oneRow 一行
     * @param valueTitleColMap 标题-列map
     * @param style 样式
     * @author 徐俊杰
     * @date 2019/6/21 16:33
     * @since v1.0
     */
    private void performanceFinishTitle(List<TitlePojo> titlePojos, int startTitle, SXSSFRow zeroRow, SXSSFRow oneRow, Map<String, Integer> valueTitleColMap, CellStyle style) {
        //处理目标完成情况的标题
        for (int i = startTitle; i < titlePojos.size(); i++) {
            TitlePojo titlePojo = titlePojos.get(i);
            int col = (i - startTitle) * 3 + startTitle;
            SXSSFCell zeroRowCell = zeroRow.createCell(col);
            zeroRowCell.setCellStyle(style);
            zeroRowCell.setCellValue(titlePojo.getValue());
            List<TitlePojo> childPojos = titlePojo.getChild();
            //处理子标题
            for (int j = 0; j < childPojos.size(); j++) {
                TitlePojo childPojo = childPojos.get(j);
                int oneRowCol = col + j;
                SXSSFCell oneRowCell = oneRow.createCell(oneRowCol);
                oneRowCell.setCellStyle(style);
                oneRowCell.setCellValue(childPojo.getValue());
                //标题-列map
                valueTitleColMap.put(childPojo.getKey(), oneRowCol);
            }
        }
    }

    /**
     * 统计表导出数据分装到sheet中
     * @param resultTableVO
     * @param chartEntity
     * @param sheet
     * @param style
     */
    public void exportStatisticsTable(ResultTableVO resultTableVO, ChartEntity chartEntity, SXSSFSheet sheet, CellStyle style) throws XbbException{
        int rowGroupSize = 0;
        int colGroupSize = 0;
        int summaryGroupSize = 0;
        if (chartEntity.getRowGroupAttr() != null) {
            rowGroupSize = chartEntity.getRowGroupAttr().size();
        }
        if (chartEntity.getColGroupAttr() != null) {
            colGroupSize = chartEntity.getColGroupAttr().size();
        }
        if (chartEntity.getSummaryAttr() != null) {
            summaryGroupSize = chartEntity.getSummaryAttr().size();
        }
        int number = 0;
        JSONObject head = resultTableVO.getHead();
        JSONArray headChild = head.getJSONArray(StringConstant.CHILD);
        JSONArray body = resultTableVO.getBody();
        // 判断是否同环比
        boolean isYearChain = EsUtil.isYearChain(chartEntity);
        try {
            // 列分组标题
            for (int i = 0; i < colGroupSize; i++) {
                SXSSFRow rowi = sheet.createRow(number);
                SXSSFCell celli = rowi.createCell(0);
                setCell(celli, headChild.getJSONObject(i).getString(StringConstant.VALUE), style);
                if (rowGroupSize > 1) {
                    CellRangeAddress region = new CellRangeAddress(number, number, 0, rowGroupSize - 1);
                    sheet.addMergedRegion(region);
                }
                sheet.setColumnWidth(i,50 * 160);
                number++;
            }
            // 行分组标题
            SXSSFRow rowGroup = sheet.createRow(number);
            if (rowGroupSize > 0) {
                JSONObject rowGroupObj = headChild.getJSONObject(colGroupSize);
                for (int j = 0; j < rowGroupSize; j++) {
                    String value = rowGroupValue(rowGroupObj, j);
                    SXSSFCell cellj = rowGroup.createCell(j);
                    setCell(cellj, value, style);
                    sheet.setColumnWidth(j,50 * 160);
                }
            } else {
                SXSSFCell cell = rowGroup.createCell(0);
                setCell(cell, "", style);
                number++;
                SXSSFCell cell1 = sheet.createRow(number).createCell(0);
                //未设置行分组，并且为小计或总计&小计 需要手动设置名称
                String str = "";
                if(chartEntity.getSum() == 0 || chartEntity.getSum() == 2){
                    str = "小计";
                }
                setCell(cell1, str, style);
            }
            number++;
            if(rowGroupSize > 0){
                if (rowGroupSize <= 3) {
                    //减小影响：原行列分组最多3个，继续执行原方法
                    for (int m = colGroupSize + 1; m < headChild.size(); m++) {
                        number = getRowExportData(sheet, style, number, headChild, m, rowGroupSize);
                    }
                } else {
                    //钻取后，行列分组字段size变大
                    number = dealWithRowExportData(sheet, style, rowGroupSize, colGroupSize, number, headChild);
                }
            }
            // 当只有列分组的情况
            if (rowGroupSize == 0) {
                rowGroupSize = 1;
            }
            //key：行索引；value：该行已经占位几个列（即几个行分组字段），所以value值是一样的，都是行分组size
            Map<Integer, Integer> rowColIndexMap = new HashMap<>(number);
            for (int n = 0; n < number; n++) {
                rowColIndexMap.put(n, rowGroupSize);
            }
            // 处理body中的数据
            int bodySize = body.size();
            if ((Objects.equals(chartEntity.getSum(), 1) || Objects.equals(chartEntity.getSum(),2)) && colGroupSize > 0 && summaryGroupSize > 0 && !isYearChain) {
                bodySize--;
            }

            if (colGroupSize <= 3) {
                // 减小影响：原行列分组最多3个，继续执行原方法
                for (int x = 0; x < bodySize; x++) {
                    getBodyColData(body.getJSONObject(x), sheet, colGroupSize, rowColIndexMap, style, summaryGroupSize);
                }
            } else {
                // 钻取可能会出现size大于3的情况，原方法getBodyColData()只处理了三列的
                for (int x = 0; x < bodySize; x++) {
                    dealDrillColExportData(body.getJSONObject(x), sheet, style, rowColIndexMap, 0);
                }
            }

            // 总计的处理, 小计 & 总计时的处理
            if ((Objects.equals(chartEntity.getSum(), 1) || Objects.equals(chartEntity.getSum(),2)) && summaryGroupSize > 0 && !isYearChain) {
                totalDataParse(resultTableVO, sheet, style, rowGroupSize, colGroupSize, summaryGroupSize, number, body, rowColIndexMap,chartEntity);
            }
        } catch (Exception e) {
            logger.error(SystemErrorCodeEnum.API_ERROR_100018.getMsg(),e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, SystemErrorCodeEnum.API_ERROR_100018.getMsg());
        }
    }

    /**
     * 递归处理导出统计表的操作，因为钻取之后列的size会大于3，但是原来的方法只支持到3
     *
     * @param colData        列数据
     * @param sheet          表格数据
     * @param rowColIndexMap 合并单元格的核心参数  key： 当前行位置    value： 当前画的excel的列位置
     * @param style          Excel样式
     * @param rowIndex       行索引， 初始值为0， 从第一行开始一行行操作
     */
    private void dealDrillColExportData(JSONObject colData, SXSSFSheet sheet, CellStyle style, Map<Integer, Integer> rowColIndexMap, int rowIndex) {
        Integer colIndex = rowColIndexMap.get(rowIndex);
        SXSSFRow nowRow = sheet.getRow(rowIndex);
        SXSSFCell cell = nowRow.createCell(colIndex);
        setCell(cell, colData.getString(StringConstant.VALUE), style);
        // 每次放入一列就需要将对应行的列索引加1
        rowColIndexMap.put(rowIndex, rowColIndexMap.get(rowIndex) + 1);
        sheet.setColumnWidth(colIndex, 50 * 160);
        JSONArray bodyChild = colData.getJSONArray(StringConstant.CHILD);
        if (CollectionUtils.isEmpty(bodyChild)) {
            // 当孩子节点为空就代表已经到了最后一列了，此时处理统计出来的计算字段的值
            JSONArray values = colData.getJSONArray(StringConstant.VALUES);
            for (int i = rowIndex + 1, size = values.size() + rowIndex + 1; i < size; i++) {
                String value = (String) values.get(i - rowIndex - 1);
                SXSSFRow valueRow = sheet.getRow(i);
                SXSSFCell valueCell = valueRow.createCell(rowColIndexMap.get(i));
                setCell(valueCell, value, numberStyle);
                // 每次放入一列就需要将对应行的列索引加1
                rowColIndexMap.put(i, rowColIndexMap.get(i) + 1);
            }
            return;
        }
        int bodyChildSize = bodyChild.size();
        rowIndex++;
        for (int m = 0; m < bodyChildSize; m++) {
            JSONObject colData1 = bodyChild.getJSONObject(m);
            // 递归处理对应的子节点
            dealDrillColExportData(colData1, sheet, style, rowColIndexMap, rowIndex);
        }
        // 此处是处理合并单元格的操作，是一层一层往上处理的，从计算字段开始往上一个一个反向处理
        if (rowColIndexMap.get(rowIndex - 1) < rowColIndexMap.get(rowIndex)) {
            CellRangeAddress region = new CellRangeAddress(rowIndex - 1, rowIndex - 1, colIndex, rowColIndexMap.get(rowIndex) - 1);
            sheet.addMergedRegion(region);
            rowColIndexMap.put(rowIndex - 1, rowColIndexMap.get(rowIndex));
        }
    }

    /**
     * 处理总计的数据，包含行总计与列总计的数据
     * @param resultTableVO
     * @param sheet
     * @param style
     * @param rowGroupSize
     * @param colGroupSize
     * @param summaryGroupSize
     * @param number
     * @param body
     * @param rowColIndexMap
     */
    private void totalDataParse(ResultTableVO resultTableVO, SXSSFSheet sheet, CellStyle style, int rowGroupSize, int colGroupSize, int summaryGroupSize, int number, JSONArray body, Map<Integer, Integer> rowColIndexMap,ChartEntity chartEntity) throws XbbException{
        try {
            // 列分组的总计处理，统计表的最下面一层的处理
            // SXSSFRow sumRow = sheet.createRow(number);
            // SXSSFCell sumCell = sumRow.createCell(0);
            // setCell(sumCell, I18nMessageUtil.getMessage(CommonConstant.TOTAL), style);
            // if (rowGroupSize > 1) {
            //     CellRangeAddress region = new CellRangeAddress(number, number, 0, rowGroupSize - 1);
            //     sheet.addMergedRegion(region);
            // }
            // List<String> summary = resultTableVO.getSummary();
            // if (CollectionUtils.isNotEmpty(summary)) {
            //     for (int k = 0, size = summary.size(); k < size; k++) {
            //         SXSSFCell cellk = sumRow.createCell(k + rowGroupSize);
            //         setCell(cellk, summary.get(k), numberStyle);
            //     }
            // }
            // 行分组的总计处理，统计表的最右侧的数据，当无列分组时不需处理
            if (colGroupSize > 0) {
                JSONObject colSummary = body.getJSONObject(body.size() - 1);
                Integer index = rowColIndexMap.get(0);
                SXSSFRow row = sheet.getRow(0);
                SXSSFCell cell = row.createCell(index);
                setCell(cell, I18nMessageUtil.getMessage(CommonConstant.TOTAL), style);
                if (colGroupSize > 1 || summaryGroupSize > 1) {
                    CellRangeAddress region = new CellRangeAddress(0, colGroupSize - 1, index, index + summaryGroupSize -1);
                    sheet.addMergedRegion(region);
                }
                summaryValuePackage(colSummary, sheet, rowColIndexMap, style, colGroupSize);
            }
            //最下方总计值数组
            List<String> underTotalValues = resultTableVO.getSummary();
            if(CollectionUtils.isNotEmpty(underTotalValues)){
                SXSSFRow row = sheet.createRow(rowColIndexMap.size());
                //获取单元格，并设置左侧总计title
                SXSSFCell cell = row.createCell(0);
                setCell(cell, I18nMessageUtil.getMessage(CommonConstant.TOTAL), style);
                //合并指定区域的单元格
                if(rowGroupSize >  1){
                    sheet.addMergedRegion(new CellRangeAddress(rowColIndexMap.size(), rowColIndexMap.size(), 0, rowGroupSize - 1));
                }
                //按行设置汇总值
                for (int i = 0; i < underTotalValues.size(); i++) {
                    SXSSFCell sumCell = row.createCell(i + rowGroupSize);
                    setCell(sumCell,underTotalValues.get(i),numberStyle);
                }
            }
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, SystemErrorCodeEnum.API_ERROR_100018.getMsg());
        }
    }

    /**
     * body中的数据处理，包含列分组的数据和汇总的信息
     * @param boyData
     * @param sheet
     * @param colGroupSize
     * @param rowColIndexMap key：行索引；value：该行已经占位几个列（即几个行分组字段），所以value值是一样的，都是行分组size
     * @param style
     * @param summarySize
     */
    private void getBodyColData(JSONObject boyData, SXSSFSheet sheet, int colGroupSize, Map<Integer, Integer> rowColIndexMap, CellStyle style, int summarySize) throws XbbException{
        try {
            if (summarySize == 0) {
                summarySize = 1;
            }
            Integer pre = rowColIndexMap.get(0);
            SXSSFRow row = sheet.getRow(0);
            SXSSFCell cell = row.createCell(pre);
            setCell(cell, boyData.getString(StringConstant.VALUE), style);
            sheet.setColumnWidth(pre, 50 * 160);
            int index = colGroupSize - 1;
            if (colGroupSize == 0) {
                rowColIndexMap.put(0, pre + 1);
                JSONArray values = boyData.getJSONArray(StringConstant.VALUES);
                for (int i = 1, size = values.size() + 1; i < size; i++) {
                    String value = (String) values.get(i - 1);
                    SXSSFRow valueRow = sheet.getRow(i);
                    SXSSFCell valueCell = valueRow.createCell(rowColIndexMap.get(i));
                    setCell(valueCell, value, numberStyle);
                    rowColIndexMap.put(i, rowColIndexMap.get(i) + 1);
                }
            } else if (colGroupSize == 1) {
                if (summarySize > 1) {
                    CellRangeAddress region = new CellRangeAddress(index, index, pre, pre + summarySize - 1);
                    sheet.addMergedRegion(region);
                }
                rowColIndexMap.put(index, pre + summarySize);
                summaryValuePackage(boyData, sheet, rowColIndexMap, style, colGroupSize);
            } else if (colGroupSize == 2) {
                JSONArray bodyChildArray1 = boyData.getJSONArray(StringConstant.CHILD);
                if (CollectionUtils.isNotEmpty(bodyChildArray1)) {
                    int childArray1Size = bodyChildArray1.size();
                    createCellFromChild(sheet, colGroupSize, rowColIndexMap, style, summarySize, index, pre, bodyChildArray1, childArray1Size);
                }
            } else if (colGroupSize == 3) {
                JSONArray bodyChildArray2 = boyData.getJSONArray(StringConstant.CHILD);
                int total = 0;
                if (CollectionUtils.isNotEmpty(bodyChildArray2)) {
                    for (int m = 0, size = bodyChildArray2.size(); m < size; m++) {
                        JSONObject group2Data = bodyChildArray2.getJSONObject(m);
                        Integer pre2 = rowColIndexMap.get(1);
                        SXSSFRow row2 = sheet.getRow(1);
                        SXSSFCell cell2 = row2.createCell(pre2);
                        setCell(cell2, group2Data.getString(StringConstant.VALUE), style);
                        JSONArray bodyChildArray3 = group2Data.getJSONArray(StringConstant.CHILD);
                        if (CollectionUtils.isNotEmpty(bodyChildArray3)) {
                            int childArray3Size = bodyChildArray3.size();
                            total += childArray3Size;
                            createCellFromChild(sheet, colGroupSize, rowColIndexMap, style, summarySize, index, pre2, bodyChildArray3, childArray3Size);
                        }
                    }

                    if (total * summarySize > 1) {
                        CellRangeAddress region = new CellRangeAddress(0, 0, pre, pre + total * summarySize - 1);
                        sheet.addMergedRegion(region);
                    }
                    rowColIndexMap.put(0, pre + total * summarySize);
                }
            }
        } catch (Exception e) {
            logger.error(SystemErrorCodeEnum.API_ERROR_100018.getMsg(),e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, SystemErrorCodeEnum.API_ERROR_100018.getMsg());
        }
    }

    private void createCellFromChild(SXSSFSheet sheet, int colGroupSize, Map<Integer, Integer> rowColIndexMap, CellStyle style, int summarySize, int index, Integer pre, JSONArray bodyChildArray, int childArraySize) throws XbbException{
        try {
            for (int n = 0; n < childArraySize; n++) {
                JSONObject groupData = bodyChildArray.getJSONObject(n);
                summaryValuePackage(groupData, sheet, rowColIndexMap, style, colGroupSize);
                Integer cursor = rowColIndexMap.get(index);
                SXSSFRow row = sheet.getRow(index);
                SXSSFCell cell = row.createCell(cursor);
                setCell(cell, groupData.getString(StringConstant.VALUE), style);
                if (summarySize > 1) {
                    CellRangeAddress region2 = new CellRangeAddress(index, index, cursor, cursor + summarySize - 1);
                    sheet.addMergedRegion(region2);
                }
                rowColIndexMap.put(index, cursor + summarySize);
            }

            if (childArraySize * summarySize > 1) {
                CellRangeAddress region1 = new CellRangeAddress(index - 1, index - 1, pre, pre + childArraySize * summarySize - 1);
                sheet.addMergedRegion(region1);
            }
            rowColIndexMap.put(index - 1, pre + childArraySize * summarySize);
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, SystemErrorCodeEnum.API_ERROR_100018.getMsg());
        }
    }

    /**
     * 汇总值的数据封装
     * @param boyData
     * @param sheet
     * @param rowColIndexMap
     * @param style
     * @param colGroupSize
     */
    private void summaryValuePackage(JSONObject boyData, SXSSFSheet sheet, Map<Integer, Integer> rowColIndexMap, CellStyle style, int colGroupSize) throws XbbException{
        try {
            JSONArray summary = boyData.getJSONArray(StringConstant.CHILD);
            for (Object obj : summary) {
                JSONObject sumData = (JSONObject) obj;
                Integer sumIndex = rowColIndexMap.get(colGroupSize);
                SXSSFRow sumRow = sheet.getRow(colGroupSize);
                SXSSFCell sumCell = sumRow.createCell(sumIndex);
                setCell(sumCell, sumData.getString(StringConstant.VALUE), style);
                sheet.setColumnWidth(sumIndex, 50 * 160);
                JSONArray values = sumData.getJSONArray(StringConstant.VALUES);
                for (int i = colGroupSize + 1, size = values.size() + colGroupSize + 1; i < size; i++) {
                    String value = (String) values.get(i - colGroupSize - 1);
                    SXSSFRow valueRow = sheet.getRow(i);
                    SXSSFCell valueCell = valueRow.createCell(rowColIndexMap.get(i));
                    setCell(valueCell, value, numberStyle);
                    rowColIndexMap.put(i, rowColIndexMap.get(i) + 1);
                }
                rowColIndexMap.put(colGroupSize, sumIndex + 1);
            }
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, SystemErrorCodeEnum.API_ERROR_100018.getMsg());
        }
    }

    /**
     * 遍历行分组的数据
     * @param sheet
     * @param style
     * @param number
     * @param headChild
     * @param m
     * @return
     */
    private int getRowExportData(SXSSFSheet sheet, CellStyle style, int number, JSONArray headChild, int m, int rowGroupSize) throws XbbException{
        JSONObject rowData1 = headChild.getJSONObject(m);
        JSONArray rowChildArray1 = rowData1.getJSONArray(StringConstant.CHILD);
        try {
            if (CollectionUtils.isNotEmpty(rowChildArray1)) {
                int pre1 = number;
                for (int p = 0, size = rowChildArray1.size(); p < size; p++) {
                    JSONObject rowData2 = rowChildArray1.getJSONObject(p);
                    JSONArray rowChildArray2 = rowData2.getJSONArray(StringConstant.CHILD);
                    if (CollectionUtils.isNotEmpty(rowChildArray2)) {
                        int pre2 = number;
                        for (int q = 0, num = rowChildArray2.size(); q < num; q++) {
                            JSONObject rowData3 = rowChildArray2.getJSONObject(q);
                            // 目前行分组最大支持3个
                            SXSSFRow rowq = sheet.createRow(number);
                            SXSSFCell cellq1 = rowq.createCell(0);
                            setCell(cellq1, rowData1.getString(StringConstant.VALUE), style);
                            SXSSFCell cellq2 = rowq.createCell(1);
                            setCell(cellq2, rowData2.getString(StringConstant.VALUE), style);
                            SXSSFCell cellq3 = rowq.createCell(2);
                            cellq3.setCellValue(rowData3.getString(StringConstant.VALUE));
                            cellq3.setCellStyle(style);
                            number++;
                        }
                        if (rowChildArray2.size() > 1) {
                            CellRangeAddress region = new CellRangeAddress(pre2, number - 1, 1, 1);
                            sheet.addMergedRegion(region);
                        }
                    } else {
                        SXSSFRow rowp = sheet.createRow(number);
                        SXSSFCell cellp1 = rowp.createCell(0);
                        setCell(cellp1, rowData1.getString(StringConstant.VALUE), style);
                        SXSSFCell cellp2 = rowp.createCell(1);
                        setCell(cellp2, rowData2.getString(StringConstant.VALUE), style);
                        number++;
                    }
                }
                if (rowChildArray1.size() > 1) {
                    CellRangeAddress region = new CellRangeAddress(pre1, number - 1, 0, 0);
                    sheet.addMergedRegion(region);
                }
            } else {
                SXSSFRow rowm = sheet.createRow(number);
                SXSSFCell cellm = rowm.createCell(0);
                setCell(cellm, rowData1.getString(StringConstant.VALUE), style);
                if (rowData1.getBoolean("isSummary") && rowGroupSize > 1) {
                    CellRangeAddress region = new CellRangeAddress(number, number, 0, rowGroupSize - 1);
                    sheet.addMergedRegion(region);
                }
                number++;
            }
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, SystemErrorCodeEnum.API_ERROR_100018.getMsg());
        }
        return number;
    }
    /**
     * 处理超过3个行分组的行数据（钻取时会超过3个）
     * @param sheet 要导出的Excel sheet
     * @param style Excel样式
     * @param rowGroupSize 行分组size
     * @param colGroupSize 列分组size
     * @param rowIndex 行索引
     * @param headChild 行表头及其行数据数组
     * @return int
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private int dealWithRowExportData(SXSSFSheet sheet, CellStyle style, int rowGroupSize, int colGroupSize, int rowIndex, JSONArray headChild) throws XbbException {
        int headSize = headChild.size();
        //headChild默认包含左侧表头及表头数据，表头前面已处理，所以此处处理表头数据时默认从表头之后的数据开始读取（每列表头及最上部列分组维度之后就是数据，所以从colGroupSize+1开始）
        for (int m = colGroupSize + 1; m < headSize; m++) {
            //表头第一行第一列的数据
            JSONObject rowData1 = headChild.getJSONObject(m);
            //表头第一行第一列的child，其实也是第二列的数据
            JSONArray rowChildArray1 = rowData1.getJSONArray(StringConstant.CHILD);
            //创建一行，开始画表头数据
            SXSSFRow rowq = sheet.createRow(rowIndex);
            //每列需要合并的行：列索引 - 需要多合并的行数（比如无需合并则为0）
            Map<Integer, Integer> mergColNumMap = new HashMap<>(headSize);
            int pre1 = rowIndex;
            //列索引
            int colIndex = 0;
            rowIndex = getRowExportDataMore(mergColNumMap, colIndex, rowq, sheet, style, rowIndex, rowData1, rowChildArray1, rowGroupSize);
            if (mergColNumMap.size() > 0) {
                for (Map.Entry<Integer, Integer> entry : mergColNumMap.entrySet()) {
                    CellRangeAddress region = new CellRangeAddress(pre1, pre1 + entry.getValue(), entry.getKey(), entry.getKey());
                    sheet.addMergedRegion(region);
                }
            }
            rowIndex++;
        }
        return rowIndex;
    }
    /**
     * 递归遍历行分组的数据（钻取时会出现分组数大于3的情况，原方法最多只处理3个分组字段的情况）
     * @param mergColNumMap 每列需要合并的行：列索引 - 需要多合并的行数（比如无需合并则为0）
     * @param colIndex 列索引
     * @param rowq 行
     * @param sheet 要导出的Excel sheet
     * @param style Excel样式
     * @param rowIndex 行索引
     * @param rowData 某行某列的数据
     * @param childList 某行某列的子数据（某行某列的下一列数据）
     * @param rowGroupSize 行分组大小
     * @return int
     * @throws
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    private int getRowExportDataMore(Map<Integer, Integer> mergColNumMap, int colIndex, SXSSFRow rowq, SXSSFSheet sheet, CellStyle style, int rowIndex, JSONObject rowData, JSONArray childList, int rowGroupSize) throws XbbException{
        try {
            //为改行rowq创建cell
            SXSSFCell cellq1 = rowq.createCell(colIndex);
            //设置数据及格式
            setCell(cellq1, rowData.getString(StringConstant.VALUE), style);
            //该行该列还有子级（即右边还有数据），则循环递归继续往下找
            if (CollectionUtils.isNotEmpty(childList)) {
                //右边有，则列索引+1
                colIndex++;
                int childSize = childList.size();
                for (int p = 0, size = childSize; p < size; p++) {
                    if (p > 0) {
                        //p大于0，说明childSize>1，即该列数据不止1行，因此需要行索引+1，并重新创建rowq
                        rowIndex++;
                        //childSize每循环一个，扩建1行
                        rowq = sheet.createRow(rowIndex);
                    }
                    //得到该行该列右侧一列的数据
                    JSONObject rowData2 = childList.getJSONObject(p);
                    //得到该行该列右侧一列的子级（即再右侧的数据）
                    JSONArray rowChildArray2 = rowData2.getJSONArray(StringConstant.CHILD);
                    //触发递归，按照以上流程继续往右侧逐列翻找、画cell及根据childSize情况扩建row
                    rowIndex = getRowExportDataMore(mergColNumMap, colIndex, rowq, sheet, style, rowIndex, rowData2, rowChildArray2, rowGroupSize);
                }
                if (childSize > 1) {
                    //当childSize不止1行时，需要对该行之前的每列进行合并
                    for (int i = 0; i < colIndex; i++) {
                        //默认无需合并，置入默认值0。
                        Integer mergeSize = mergColNumMap.getOrDefault(i, 0);
                        //如果之前已经有需要合并的，可能已经塞入该map值。因此此处是用map内原值加新的要多合并的行值
                        //此处减一是因为，要排除其自身所在的一行。比如childSize=1时无需扩充行，无需合并行，childSize=2时，需要扩充合并1行
                        mergeSize = mergeSize + childSize - 1;
                        mergColNumMap.put(i, mergeSize);
                    }
                }
            } else {
                if (Objects.equals(colIndex, 0)) {
                    //递归方法外部已优先直接创建行
//                    SXSSFRow rowm = sheet.createRow(rowIndex);
                    SXSSFCell cellm = rowq.createCell(0);
                    setCell(cellm, rowData.getString(StringConstant.VALUE), style);
                    if (rowData.getBoolean("isSummary") && rowGroupSize > 1) {
                        CellRangeAddress region = new CellRangeAddress(rowIndex, rowIndex, 0, rowGroupSize - 1);
                        sheet.addMergedRegion(region);
                    }
                }
            }
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, SystemErrorCodeEnum.API_ERROR_100018.getMsg());
        }
        return rowIndex;
    }

    private void setCell(SXSSFCell cell, String value, CellStyle style) {
        cell.setCellStyle(style);
        cell.setCellValue(value);
    }


    /**
     * 处理行分组层级关系，找到每层对应的value
     * @param rowGroupObj
     * @param size
     * @return
     */
    public String rowGroupValue(JSONObject rowGroupObj, int size) {
        if (size == 0) {
            return rowGroupObj.getString(StringConstant.VALUE);
        }
        JSONArray child = rowGroupObj.getJSONArray(StringConstant.CHILD);
        if (CollectionUtils.isNotEmpty(child)) {
            size--;
            return rowGroupValue(child.getJSONObject(0), size);
        }
        return "";
    }

    /**
     * 格式设置 垂直水平居中，设置sheet默认row高度
     * @param cellStyle cell类型
     * @param sheet sheet
     * @author zhouwq
     * @date 2019/6/20 10:38
     */
    public void setWorkBookStyle(CellStyle cellStyle, SXSSFSheet sheet){
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        sheet.setDefaultRowHeight((short) (2 * 256));
    }

    /**
     * 导出初始化
     *
     * @param formDataListDTO 表单信息
     * @param userId 用户ID
     * @param corpId 公司ID
     * @throws XbbException error
     * @author zhouwq
     * @date 2019/6/10 13:17
     */
    public void initChartExport(FormDataListDTO formDataListDTO, String userId, String corpId) throws XbbException {
        formDataListDTO.setUserId(userId);
        formDataListDTO.setCorpid(corpId);
        // 读取导出任务状态缓存
        String hashKey = formDataListDTO.getCorpid() + "_" + formDataListDTO.getUserId();
        ExportStatusPojo exportStatusPojo = JsonHelperUtil.parseObject(paasRedisHelper.getValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey), ExportStatusPojo.class);
        if (Objects.nonNull(exportStatusPojo) && Objects.equals(exportStatusPojo.getFinish(), BasicConstant.TWO)) {
            // 上次导出任务未结束
            throw new XbbException(ImportErrorCodeEnum.API_ERROR_235004);
        }else {
            // 上次导出状态缓存清除
            paasRedisHelper.removeValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey);
            exportStatusPojo = new ExportStatusPojo();
            BeanUtil.copyProperties(exportStatusPojo, formDataListDTO);
            paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, exportStatusPojo, RedisConstant.SHORT_DURATION);
        }
    }

    public void exPortData(ExportFormDataVO exportFormDataVO, FormDataListDTO formDataListDTO, ChartResultVO chartResultVO) throws XbbException {
        List<ChartResultDetailVO> list = chartResultVO.getChartList();
        SXSSFWorkbook workbook = new SXSSFWorkbook();
        CellStyle style = workbook.createCellStyle();
        CellStyle numberStyle = workbook.createCellStyle();
        SXSSFSheet sheet = workbook.createSheet();
        //垂直水平居中
        setWorkBookStyle(style, sheet);
        List<String> strings = Arrays.asList(SystemCodeEnum.MARKET_ACTIVITY_CONVERSION.getSystemCode(), SystemCodeEnum.MARKET_ACTIVITY_ROI_ACTIVITY.getSystemCode(), SystemCodeEnum.ACTIITY_CONVERSION_ANAYALSIS.getSystemCode());
        for (ChartResultDetailVO chartResultDetailVO : list) {
            ResultTableVO resultTableVO = chartResultDetailVO.getTable();
            if (resultTableVO != null) {
                Integer chartType = resultTableVO.getChartType();
                if (Objects.equals(ChartTypeEnum.DATA_QUERY_TABLE.getCode(), chartType)) {
                    //查询表导出
                    exportQueryTableAssemble(resultTableVO, sheet, style);
                } else if (Objects.equals(ChartTypeEnum.DATA_STATISTICS_TABLE.getCode(), chartType)) {
                    //统计表导出
                    if (resultTableVO.getPageHelper().getRowsCount() > ExportConstant.EXPORT_MAX_TOTAL) {
                        throw new XbbException(ExportErrorCodeEnum.API_ERROR_234001);
                    }
                    if (resultTableVO.getColTotal() > ExportConstant.EXPORT_COL_MAX_NUM) {
                        throw new XbbException(ExportErrorCodeEnum.API_ERROR_234005.getCode(), ErrorMessageConstant.COL_DATA_EXPORT_LIMIT);
                    }
                    style.setAlignment(HorizontalAlignment.LEFT);
                    numberStyle.setAlignment(HorizontalAlignment.RIGHT);
                    numberStyle.setVerticalAlignment(VerticalAlignment.CENTER);
                    ChartExportHelp.numberStyle = numberStyle;
                    ChartEntity chartEntity = chartResultDetailVO.getChartEntity();
                    //使用默认值1000，等分页改为最小维度之后再用这个
//                        sheet.setRandomAccessWindowSize(resultTableVO.getPageHelper().getRowsCount() * 2 + 6);
                    sheet.setRandomAccessWindowSize(Math.max(1006,resultTableVO.getPageHelper().getRowsCount() * 2 + 6));
                    exportStatisticsTable(resultTableVO, chartEntity, sheet, style);
                } else if (Objects.equals(ChartTypeEnum.TARGET_CHART.getCode(), chartType)) {
                    Integer groupSize = chartResultDetailVO.getGroupSize();
                    //指标图导出
                    exportStatisticsTableAssemble(resultTableVO, groupSize, sheet, style);
                } else {
                    //系统图表
                    String systemCode = resultTableVO.getSystemCode();
                    if (Objects.equals(systemCode, SystemCodeEnum.INCOME_AND_EXPENDITURE.getSystemCode()) ||
                            Objects.equals(systemCode, SystemCodeEnum.CUSTOMER_DELIVERY_ANALYSIS_CHART.getSystemCode())) {
                        exportSystemChartAssemble4BusinessData(resultTableVO, sheet, style);
                    } else if (Objects.equals(systemCode, SystemCodeEnum.OPPORTUNITY_STAGE_CHART.getSystemCode())){
                        exportSystemChartAssemble4OpportunityStage(resultTableVO, sheet, style);
                    } else if (strings.contains(systemCode)){
                        List<List<ResultDataTableVO>> marketData = resultTableVO.getMarketData();
                        resultTableVO.setData(marketData);
                        exportSystemChartAssemble(resultTableVO, sheet, style);
                    } else {
                        exportSystemChartAssemble(resultTableVO, sheet, style);
                    }
                }
                //设置表名
                exportFormDataVO.setName(resultTableVO.getTableName() + DateTimeUtil.getString(DateTimeUtil.SDFDate));
            }
        }
        exportFormDataVO.setWorkbook(workbook);
        exportFormDataVO.setName(exportFormDataVO.getName().replace("\\+","+")+ ImportConstant.EXCEL_SUFFIX);
        // OSS上传文件
        String downloadUrl = handleImportService.exportAsync(formDataListDTO, exportFormDataVO, ImportConstant.EXCEL_SUFFIX);
        exportFormDataVO.setUrl(downloadUrl);
    }

    /**
     * 导出的接口入参idIn已经改为 chartIdIn，
     * 但是穿透reuslt还是直接使用的idIn，因此要做一层处理
     *
     * @param chartResultDTO
     * @author zyy
     * @date 2022/11/24
     * @version v1.0
     */
    public void replaceCharIdIn(ChartPenetrateResultDTO chartResultDTO){
        if(CollectionUtils.isNotEmpty(chartResultDTO.getChartIdIn())){
            //导出的接口入参idIn已经改为 chartIdIn，
            //但是穿透result还是直接使用的idIn，因此要做一层处理
            List<Long> customIdList = chartResultDTO.getChartIdIn()
                    .stream()
                    .filter(value -> Objects.equals(value.getStatisticsType(), StatisticsTypeEnum.CUSTOM_STATISTIC.getCode()))
                    .map(ChartIdPojo::getId)
                    .collect(Collectors.toList());
            chartResultDTO.setIdIn(customIdList);
        }
    }


}
